/*@@

	Copyright (c) 2010 BlueSky LTD. All rights reserved. 

	Created_datetime : 	2010-6-21

	File Name :	base_packfile.cpp

	Author : liusiliang (siliangliu@msn.com)

	Description : 

@@*/


#include <cstdio>
#include <cstring>

#include "base/base_str.h"
#include "base/base_packmgr.h"
#include "base/base_packfile.h"

namespace BLK
{
	// 文件读取模式 0 = 优先从磁盘读取 1 = 优先从文件包读取
	PackFile::ReadMode PackFile::m_ReadMode = PackFile::FIRST_LOADFROM_DISK;

	/*
	 *	功能:	构造函数	
	 */
	PackFile::PackFile(void)
	{
		m_PackRef.nPackIndex = -1;
		m_PackRef.uId = 0;
	}

	/*
	 *	功能:	析构函数	
	 */
	PackFile::~PackFile(void)
	{
		Close();
	}

	/*
	 *	功能:	判断此文件是否从包中打开的
	 *	返回:	是否从包中打开的
	 */
	bool PackFile::IsFileInPak(void)
	{
		return (m_PackRef.nPackIndex >= 0 && 
				 m_PackRef.uId);
	}

	/*
	 *	功能:	打开一个文件, 先寻找当前目录下是否有同名的单独文件
	 *	参数:	pszFileName	文件路径
	 *	返回:	是否成功打开
	 */
	bool PackFile::Open(const char* pszFileName)
	{
		if(pszFileName == NULL || pszFileName[0] == 0)
        {
                
			return false;
        }

		bool bOk = false;
		Close();

		char szPackNameAddtion[MAXPATH_];
		::memset(szPackNameAddtion, 0, MAXPATH_);

        ::strncpy(szPackNameAddtion, pszFileName, MAXPATH_);
		//BLK::StringFixSlash(szPackNameAddtion);

		// Modified By Lulu
		if(m_ReadMode == FIRST_LOADFROM_DISK)	// 优先从磁盘读取
		{
            std::locale save_local = std::locale::global(std::locale(""));
			m_File.open(szPackNameAddtion, std::ios::in | std::ios::binary);
            std::locale::global(save_local);

            if(!(m_File.good()))
			{
				bOk = PackMgr::Singleton().FindElemFile(szPackNameAddtion, m_PackRef);
			}
			else
			{
				bOk = true;
			}
		}
		else	// 优先从文件包读取
		{
			bOk = PackMgr::Singleton().FindElemFile(szPackNameAddtion, m_PackRef);
			if(bOk == false)
			{
				m_File.open(szPackNameAddtion);
			}
		}
		
		return bOk;
	}

	/*
	 *	功能:	从文件中读取数据
	 *	参数:	pBuffer		缓冲区指针
	 *			dwSize		要读取的长度
	 *	返回:	读到的字节长度
	 */
	unsigned long PackFile::Read(
		void* pBuffer, 
		unsigned uSize)
	{
		if(m_PackRef.nPackIndex >= 0)
		{
			if(PackMgr::Singleton().ElemFileRead(
					m_PackRef, 
					pBuffer, 
					uSize) == false)
				uSize = 0;
		}
		else
		{
			// Modified By Lulu
			m_File.read((char*)pBuffer, uSize);
			uSize = m_File.gcount();
		}
		return uSize;
	}

	/*
	 *	功能:	文件读指针定位
	 *	参数:	lOffset			偏移量
	 *			dwMethod		定位方法
	 *	返回:	文件的指针
	 */
	unsigned long PackFile::Seek(int nOffset, FileOrigin uMethod)
	{
		if(m_PackRef.nPackIndex >= 0)
		{
			if(uMethod == FileBegin)
				m_PackRef.nOffset = nOffset;
			else if(uMethod == FileEnd)
				m_PackRef.nOffset = m_PackRef.nSize + nOffset;
			else
				m_PackRef.nOffset += nOffset;

			if(m_PackRef.nOffset > m_PackRef.nSize)
				m_PackRef.nOffset =  m_PackRef.nSize;
			else if(m_PackRef.nOffset < 0)
				m_PackRef.nOffset = 0;

			nOffset = m_PackRef.nOffset;
		}
		else
		{
			// Modified By Lulu
			int method = uMethod;
			m_File.seekg(nOffset, (std::ios::seekdir)method);
			nOffset = m_File.tellg();

		}
		return nOffset;
	}

	/*
	 *	功能:	返回文件的指针
	 *	返回:	文件的指针
	 */
	unsigned long PackFile::Tell(void)
	{
		unsigned long ulOffset;
		// Modified By Lulu
		if(m_ReadMode == PackFile::FIRST_LOADFROM_PACK &&
			m_PackRef.nPackIndex >= 0)
				ulOffset = m_PackRef.nOffset;
		else
		{
			ulOffset = m_File.tellg();
		}

		return ulOffset;
	}

	/*
	 *	功能:	返回文件大小
	 *	返回:	文件的大小 in bytes
	 */
	unsigned long PackFile::Size(void)
	{
		unsigned long dwSize;
		if(m_PackRef.nPackIndex >= 0)
			dwSize = m_PackRef.nSize;
		else
		{
			// Modified By Lulu
			std::ios::pos_type pos = m_File.tellg();
			m_File.seekg(0, std::ios::end);
			dwSize = m_File.tellg();
			m_File.seekg(pos, std::ios::beg);
		}

		return dwSize;
	}

	/*
	 *	功能:	关闭文件
	 */
	void PackFile::Close(void)
	{
		if(m_PackRef.nPackIndex >= 0)
		{
			m_PackRef.nPackIndex = -1;
			m_PackRef.uId = 0;
		}
		else
		{
			// Modified By Lulu
			if(!m_File.good())
				m_File.close();
		}
	}

	/*
	 *	功能:	设置文件读取模式
	 *	参数:	nFileMode	文件读取模式 0 = 优先从磁盘读取 1 = 优先从文件包读取
	 */
	void PackFile::SetPackFileMode(ReadMode nFileMode)
	{
		m_ReadMode = nFileMode;
	}

};
